package org.zero.common.core.util.spring.web.context.request.jakarta;

import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import lombok.experimental.UtilityClass;
import org.springframework.http.MediaType;
import org.springframework.http.server.RequestPath;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.ServletRequestPathUtils;

import java.util.Optional;

/**
 * @author Zero (cnzeropro@qq.com)
 * @since 2022/11/23
 */
@UtilityClass
public class RequestUtil {
    public static Optional<RequestAttributes> getRequestAttributesOpt() {
        return Optional.ofNullable(RequestContextHolder.getRequestAttributes());
    }

    /**
     * 获取当前 HttpServletRequest
     */
    public static HttpServletRequest getHttpServletRequest() {
        return getHttpServletRequestOpt().orElse(null);
    }

    /**
     * 获取当前 HttpServletRequest
     */
    public static Optional<HttpServletRequest> getHttpServletRequestOpt() {
        return getRequestAttributesOpt()
                .filter(ServletRequestAttributes.class::isInstance)
                .map(ServletRequestAttributes.class::cast)
                .map(ServletRequestAttributes::getRequest);
    }

    /**
     * protocol://host[:port]/path?query#fragment
     * <p>
     * 示例：http://127.0.0.1:8080/demo/test?a=bbb <br>
     * 结果：http://127.0.0.1:8080/demo
     */
    public static String getDomain() {
        return getHttpServletRequestOpt()
                .map(org.zero.common.core.util.jakarta.servlet.RequestUtil::getDomain)
                .orElse(null);
    }

    /**
     * protocol://host[:port]/path?query#fragment
     * <p>
     * 示例：http://127.0.0.1:8080/demo/test?a=bbb <br>
     * 结果：http://127.0.0.1:8080
     */
    public static String getServerDomain() {
        return getHttpServletRequestOpt()
                .map(org.zero.common.core.util.jakarta.servlet.RequestUtil::getServerDomain)
                .orElse(null);
    }

    public static String getContentType() {
        return getHttpServletRequestOpt()
                .map(RequestUtil::getContentType)
                .orElse(null);
    }

    private static String getContentType(ServletRequest request) {
        return request.getContentType();
    }

    public static MediaType getMediaType() {
        return getHttpServletRequestOpt()
                .map(RequestUtil::getMediaType)
                .orElse(null);
    }

    public static MediaType getMediaType(ServletRequest request) {
        return Optional.ofNullable(request)
                .map(RequestUtil::getContentType)
                .map(MediaType::valueOf)
                .orElse(null);
    }

    public static Optional<RequestPath> getRequestPathOpt() {
        return getHttpServletRequestOpt().map(ServletRequestPathUtils::getParsedRequestPath);
    }

    public static RequestPath getRequestPath() {
        return getRequestPathOpt().orElse(null);
    }
}
